import { lazy, ReactElement, Suspense } from 'react'
import { createBrowserRouter, Navigate, redirect, useRouteError } from 'react-router-dom'
import { Flex, Spin } from 'antd'
import { __DEV__, getItem, getUrlSearchParams, hsHandleUserAuth, message, setItem, TOKEN } from '@hs-admin/utils'
import { getUserInfo, loginByCode } from '@/api/login.ts'
import { commonRouteLoader } from '@hs-admin/node'

const Login = lazy(() => import('@/views/Login/LoginPage.tsx'))
const Layout = lazy(() => import('@/views/Layout/Layout.tsx'))
const Home = lazy(() => import('@/views/Home/HomePage.tsx'))
const BiomedicalArea = lazy(() => import('@/views/BiomedicalArea/index.tsx'))
const CompanyList1 = lazy(() => import('@/views/Company/CompanyList1.tsx'))
const CompanyList2 = lazy(() => import('@/views/Company/CompanyList2.tsx'))
const Demo = lazy(() => import('@/views/Demo/index.tsx'))
const PersonalCenter = lazy(() =>
  import('@hs-server/components').then((it) => ({
    default: it.FinanceLayout
  }))
)
const FavorCompany = lazy(() =>
  import('@hs-server/components').then((it) => ({
    default: it.FavorCompany
  }))
)
const MyExport = lazy(() =>
  import('@hs-server/components').then((it) => ({
    default: it.MyExport
  }))
)
const ExportCompanyList = lazy(() =>
  import('@hs-server/components').then((it) => ({
    default: it.ExportCompanyList
  }))
)
const CompanyReport = lazy(() =>
  import('@hs-server/components').then((it) => ({
    default: it.CompanyReport
  }))
)
const ExternalDataServiceOrder = lazy(() =>
  import('@hs-server/components').then((it) => ({
    default: it.ExternalDataServiceOrder
  }))
)
const InnerDataServiceOrder = lazy(() =>
  import('@hs-server/components').then((it) => ({
    default: it.InnerDataServiceOrder
  }))
)
const Suggestion = lazy(() =>
  import('@hs-server/components').then((it) => ({
    default: it.Suggestion
  }))
)
const CompanyIframe = lazy(() => import('@/views/Company/CompanyIframe.tsx'))
const Monitors = lazy(() => import('@/views/Monitors/index.tsx'))

function withLoading(component: ReactElement) {
  return <Suspense fallback={<Spin />}>{component}</Suspense>
}

const handleCodeLogin = async (url: string) => {
  const code = getUrlSearchParams('code', url)
  if (code) {
    try {
      const res = await loginByCode({ code })
      setItem(TOKEN, res.access_token)
      const myInfo = await getUserInfo()
      hsHandleUserAuth(myInfo)
      if (url.includes('returnto')) {
        return getUrlSearchParams('returnto') || '/'
      } else {
        return '/'
      }
    } catch (e: any) {
      message.error(e)
      return '/login?fail=true'
    }
  }
}

const ErrorBoundary = () => {
  const error = useRouteError() as {
    message?: string
    status?: number
  }
  let text = ''
  if (error.message?.includes('Failed to fetch dynamically imported module')) {
    text = '页面已发新版，请强刷页面或清空缓存'
  } else if (error.status === 404) {
    text = '页面不存在'
  } else if (error.status === 403) {
    text = '您没有该页面权限'
  } else {
    text = JSON.stringify(error.message)
    console.error(error)
  }
  return (
    <Flex align="center" justify="center" style={{ height: '100%' }}>
      <h1>{text}</h1>
    </Flex>
  )
}

const subRoutes: any[] = [
  {
    name: '首页',
    path: 'home',
    element: withLoading(<Home />)
  },
  {
    name: '生物医药专区',
    path: 'biomedicalArea',
    element: withLoading(<BiomedicalArea from="生物医药专区" />)
  },
  {
    name: '新能源专区',
    path: 'newEnergy',
    element: withLoading(<BiomedicalArea from="新能源专区" />)
  },
  {
    name: '汽车专区',
    path: 'carArea',
    element: withLoading(<BiomedicalArea from="汽车专区" />)
  },
  {
    name: '新材料专区',
    path: 'advancedMaterialArea',
    element: withLoading(<BiomedicalArea from="新材料专区" />)
  },
  {
    name: '未来产业专区',
    path: 'futureArea',
    element: withLoading(<BiomedicalArea from="未来产业专区" />)
  },
  {
    name: '数字经济专区',
    path: 'digitalEconomy',
    element: withLoading(<BiomedicalArea from="数字经济专区" />)
  },
  {
    name: '高端装备专区',
    path: 'highEquipment',
    element: withLoading(<BiomedicalArea from="高端装备专区" />)
  },
  {
    name: '农业专区',
    path: 'agriculture',
    element: withLoading(<BiomedicalArea from="农业专区" />)
  },
  {
    name: '食品专区',
    path: 'food',
    element: withLoading(<BiomedicalArea from="食品专区" />)
  },
  {
    name: '传统制造业专区',
    path: 'traditionaLindustry',
    element: withLoading(<BiomedicalArea from="传统制造业专区" />)
  },
  {
    name: '数字创意专区',
    path: 'digitalCreativity',
    element: withLoading(<BiomedicalArea from="数字创意专区" />)
  },
  {
    name: '创新资质企业',
    path: 'CompanyList1',
    element: withLoading(<CompanyList1 />)
  },
  {
    name: '重点企业榜单',
    path: 'CompanyList2',
    element: withLoading(<CompanyList2 />)
  },
  {
    name: '个人中心',
    path: 'PersonalCenter',
    element: withLoading(<PersonalCenter />),
    children: [
      {
        name: '个人中心空白',
        path: '',
        element: withLoading(<Navigate to="/PersonalCenter/favorCompany" replace />)
      },
      {
        name: '收藏企业',
        path: 'favorCompany',
        element: withLoading(<FavorCompany source="industryWarning" />)
      },
      {
        name: '我的导出',
        path: 'myExport',
        element: withLoading(<MyExport />),
        children: [
          {
            name: '企业列表导出',
            path: 'companyList',
            element: withLoading(<ExportCompanyList source="industryWarning" />)
          },
          {
            name: '企业报告导出',
            path: 'companyReport',
            element: withLoading(<CompanyReport />)
          }
        ]
      },
      {
        name: '我的订单',
        path: 'myOrder',
        children: [
          {
            name: '数据服务订单',
            path: 'externalDataService',
            element: withLoading(<ExternalDataServiceOrder />)
          },
          {
            name: '内部数据服务订单',
            path: 'innerDataService',
            element: withLoading(<InnerDataServiceOrder />)
          }
        ]
      }
    ]
  },
  {
    name: '企业探查',
    path: 'exploreCompany',
    element: withLoading(<CompanyIframe />)
  },
  {
    name: '提建议',
    path: 'suggestion',
    element: withLoading(<Suggestion />)
  },
  {
    name: '监测',
    path: 'monitors',
    element: withLoading(<Monitors />)
  }
]
if (__DEV__) {
  subRoutes.push({
    name: 'demo',
    path: 'demo',
    element: withLoading(<Demo />)
  })
}

const allRoutes = [
  ...subRoutes.reduce(
    (
      previousValue: Array<{
        name: string
        rawPath: string
        regPath: string
        belong: string
        parents: string[]
      }>,
      currentValue
    ) => {
      const item = {
        name: currentValue.name,
        rawPath: currentValue.path,
        regPath: currentValue.path.replace(/(:.*?)(\/|$)/g, '(w|-)*$2'),
        belong: currentValue.belong,
        parents: []
      }
      const theChildren =
        currentValue.children?.map((it: { name: any; path: any }) => ({
          name: it.name,
          rawPath: `${currentValue.path}/${it.path}`,
          regPath: `${currentValue.path}/${it.path}`.replace(/(:.*?)(\/|$)/g, '(w|-)*$2'),
          belong: currentValue.belong,
          parents: [item.rawPath]
        })) ?? []
      return previousValue.concat(item, ...theChildren)
    },
    []
  )
]

const getWhichBelong = (prefix: string) => (fullPath: string) => {
  const arr = allRoutes.map((it) => ({
    ...it,
    fullRegPath: new RegExp(`${prefix}${it.regPath}`)
  }))
  arr.reverse()

  const theOne = arr.find((it) => it.fullRegPath.test(fullPath))

  return {
    belong: theOne?.belong ?? '',
    name: theOne?.name ?? '',
    parents: theOne?.parents.map((it) => `${prefix}${it}`) ?? [],
    rawPath: theOne?.rawPath ?? '',
    regPath: theOne?.regPath ?? ''
  }
}

const router = createBrowserRouter([
  {
    path: '/',
    element: withLoading(<Layout />),
    children: [
      {
        path: '',
        element: withLoading(<Navigate to="/home" replace />)
      },
      ...subRoutes.map((it) => ({
        ...it,
        loader: commonRouteLoader
      }))
    ],
    loader: async ({ request }) => {
      const token = getItem(TOKEN)
      if (!token) {
        const path = await handleCodeLogin(request.url)
        return redirect(path || '/login')
      }
      return null
    },
    errorElement: <ErrorBoundary />
  },
  {
    path: '/login',
    element: withLoading(<Login />),
    loader: async ({ request }) => {
      const path = await handleCodeLogin(request.url)
      if (path) return redirect(path)
      return null
    },
    errorElement: <ErrorBoundary />
  }
])

export const topMenus = [
  ...subRoutes
    .filter((it) => it.isTopMenu)
    .map((it) => ({
      label: it.name,
      path: `/${it.path}`
    }))
]
export const getSubRoutesBelong = getWhichBelong('/')
export default router
